/*
** serveur.c for zappy in /home/fassi_c//zappy2/zappouet/server/serveur_dir
**
** Made by clement fassi
** Login   <fassi_c@epitech.net>
**
** Started on  Wed Jun 29 12:03:00 2011 clement fassi
** Last update Sat Jul  9 17:41:02 2011 clement fassi
*/

#include <sys/wait.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

#include "serveur.h"
#include "./utils/utils.h"

Loop		*initloop(int s)
{
  Loop		*this;

  this = malloc(sizeof(Loop));
  this->buf = malloc(256 * sizeof(char));
  this->list = NULL;
  this->tmp = NULL;
  this->nb = 0;
  this->j = 0;
  this->fdmax = s;
  return (this);
}

void		init(Loop *this, int s)
{
  bzero(this->buf, strlen(this->buf));
  FD_ZERO(&(this->readf));
  FD_SET(s, &(this->readf));
  FD_ZERO(&(this->writef));
  FD_SET(s, &(this->writef));
  while (this->tmp)
    {
      FD_SET(this->tmp->cs, &(this->readf));
	  this->tmp = this->tmp->next;
    }
  if (select(this->fdmax + 1, &(this->readf), \
	     &(this->writef), NULL, NULL) < 0)
    {
      fputs("Error: can't select.\n", stderr);
      exit(EXIT_FAILURE);
    }
}

void		verif(Loop *this, int s, struct sockaddr_in client_sin, \
		      socklen_t client_sin_len)
{
  this->tmp = this->list;
  while (this->tmp)
    {
      bzero(this->buf, strlen(this->buf));
      if (FD_ISSET(this->tmp->cs, &(this->readf)))
	if ((this->nb = xread(this->tmp->cs, this->buf, 256)) > 1)
	  bzero(this->buf, sizeof(this->buf));
      this->tmp = this->tmp->next;
	}
  if (FD_ISSET(s, &(this->readf)))
    if ((this->j = accept(s, (struct sockaddr *)&client_sin, \
			  &client_sin_len)))
      {
	put_in_list(&(this->list), this->j);
	puts("New client connected.");
	FD_SET(this->j, &(this->readf));
      }
  this->fdmax = get_max_fd(this->list, s);
}

static void	loop(int s, struct sockaddr_in client_sin, \
		     socklen_t client_sin_len)
{
  Loop		*this = initloop(s);

  this->tmp = xmalloc(sizeof(*(this->tmp)));
  while (42)
    {
      init(this, s);
      verif(this, s, client_sin, client_sin_len);
    }
}

int                     main(int argc, char **argv)
{
  int                   s;
  struct sockaddr_in    sin;
  struct sockaddr_in    client_sin;
  socklen_t		client_sin_len;
  int                   port;

  if (argc == 2)
    {
      s = socket(AF_INET, SOCK_STREAM, 0);
      port = atoi(argv[1]);
      sin.sin_family = AF_INET;
      sin.sin_port = htons(port);
      sin.sin_addr.s_addr = INADDR_ANY;
      bind(s, (struct sockaddr*)&sin, sizeof(sin));
      listen(s, 16);
      client_sin_len = sizeof(client_sin);
      loop(s, client_sin, client_sin_len);
      return (0);
    }
  fputs("Usage: ./serveur <port>\n", stderr);
  return (-1);
}
